/*-----------------------------------------------------------------------------
	The contents of this file are subject to the Mozilla Public License
	Version 1.1 (the "License"); you may not use this file except in
	compliance with the License. You may obtain a copy of the License at
	http://www.mozilla.org/MPL/
	
	Software distributed under the License is distributed on an "AS IS"
	basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
	License for the specific language governing rights and limitations
	under the License.
	
	The Original Code is Fever Framework code.
	
	The Initial Developer of the Original Code is Romain Ecarnot.
	Portions created by Initial Developer are Copyright (C) 2006
	the Initial Developer. All Rights Reserved.
	
	Contributor(s):
	
	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.
-----------------------------------------------------------------------------*/

import com.bourre.data.collections.IndexedArray;
import com.bourre.data.iterator.ArrayIterator;
import com.bourre.data.iterator.Iterator;

import fever.data.file.File;
import fever.data.file.FileFilterCollection;
import fever.exception.IllegalArgumentException;

/**
 * <strong>FileFilter</strong> allow file filtering definition.
 * 
 * <p>Example
 * {@code
 *   var asFilter : FileFilter = new FileFilter( "ActionScript files" );
 *   asFilter.addExtension( "as" );
 * }
 * 
 * @author Romain Ecarnot
 */
class fever.data.file.FileFilter implements FileFilterCollection
{	
	//-------------------------------------------------------------------------
	// Private properties
	//-------------------------------------------------------------------------
	
	private static var _swfFilter : FileFilter;
	private static var _picFilter : FileFilter;	private static var _assetFilter : FileFilter;	private static var _flvFilter : FileFilter;	private static var _xmlFilter : FileFilter;	private static var _allFilter : FileFilter;
	
	private var _description : String;
	private var _extensions : IndexedArray;
	
	
	//-------------------------------------------------------------------------
	// Public API
	//-------------------------------------------------------------------------
	
	/**
	 * Retuns a pre build filter for Flash compliant image.
	 */
	public static function getFlashImageFilter() : FileFilter
	{
		if( !_picFilter )
		{
			_picFilter = new FileFilter( 'Flash compatible image' );
			_picFilter.addExtensions( [ 'jpg', 'jpeg', 'png' ] );
		}
		
		return _picFilter;	
	}
	
	/**
	 * Retuns a pre build filter for swf files ( *.swf ).
	 */
	public static function getFlashFileFilter() : FileFilter
	{
		if( !_swfFilter )
		{
			_swfFilter = new FileFilter( 'Flash file' );
			_swfFilter.addExtension( 'swf' );
		}
		
		return _swfFilter;
	}
	
	/**
	 * Retuns a pre build filter for flash asset files ( *.swf, *.png, *.jpg ).
	 */
	public static function getFlashAssetFilter() : FileFilter
	{
		if( !_assetFilter )
		{
			_assetFilter = new FileFilter( 'Flash compliant asset' );
			_assetFilter.addExtensions( [ 'swf', 'jpg', 'jpeg', 'png' ] );
		}
		
		return _assetFilter;
	}
	
	/**
	 * Retuns a pre build filter for Flash video ( *.flv ).
	 */
	public static function getFlashVideoFilter() : FileFilter
	{
		if( !_flvFilter )
		{
			_flvFilter = new FileFilter( 'Flash video' );
			_flvFilter.addExtension( 'flv' );
		}
		
		return _flvFilter;
	}
	
	/**
	 * Retuns a pre build filter for xml files ( *.xml ).
	 */
	public static function getXMLFilter() : FileFilter
	{
		if( !_xmlFilter )
		{
			_xmlFilter = new FileFilter( 'XML File' );
			_xmlFilter.addExtension( 'xml' );
		}
		
		return _xmlFilter;
	}
	
	/**
	 * Retuns a pre build filter for All files ( *.* ).
	 */
	public static function getAllFilesFilter() : FileFilter
	{
		if( !_allFilter )
		{
			_allFilter = new FileFilter( 'All files' );
			_allFilter.addExtension( '*' );
		}
		
		return _allFilter;
	}
	
	/**
	 * Constructor
	 * 
	 * @param filter description
	 */
	public function FileFilter( description : String )
	{
		super();
		
		setDescription( description );
		_extensions = new IndexedArray();
	}
	
	/**
	 * Returns the description of this filter.
	 */
	public function getDescription() : String
	{
		return _description;
	}
	
	/**
	 * Sets the description of this filter.
	 */
	public function setDescription( description : String) : Void
	{
		if( !description )
		{
			throw new IllegalArgumentException( 'Description can\'t be \'null\' or \'undefined\'' );
		}
		
		_description = description;
	}
	
	/**
	 * Adds a new possible extension to the filter.
	 */
	public function addExtension( extension : String ) : Boolean
	{
		if( !extension )
		{
			throw new IllegalArgumentException( 'Extension can\'t be \'null\' or \'undefined\'' );
		}
		
		return _extensions.push(extension);
	}
	
	/**
	 * Adds extensions list to the filter
	 * 
	 * @param extensions Array list of extensions
	 */
	public function addExtensions( extensions : Array ) : Void
	{
		if( !extensions )
		{
			throw new IllegalArgumentException( 'Extension can\'t be \'null\' or \'undefined\'' );
		}
		
		var len : Number = extensions.length;
		for( var i : Number = 0; i < len; i++ )
			_extensions.push( extensions[i] );
	}
	
	/**
	 * Returns extensions list defined for this filter.
	 */
	public function getExtensions() : IndexedArray
	{
		return _extensions;	
	}
	
	/**
	 * Removes passed-in extension from filter.
	 */
	public function removeExtension( extension : String ) : Boolean
	{
		return _extensions.remove(extension);
	}
	
	/**
	 * Indicates if extensions are defined in current filter.
	 */
	public function isEmpty() : Boolean
	{
		return _extensions.isEmpty();	
	}
	
	/**
	 * Resets filter extension list.
	 */
	public function clearExtensions() : Void
	{
		_extensions.init();
	}
	
	/**
	 * Builds and returns a Flash FileReference compliant type array. 
	 */
	public function toFileReferenceFilter() : Object
	{
		var o : Object = new Object();
		o.description = _description;
		o.extension = getString( ';' );
		
		return o;	
	}
	
	/**
	 * Returns extensions list in string format using passed-in {@code delimiter} 
	 * character.
	 * 
	 * @param delimiter ( optional ) Delimiter character. ( default use ";" )
	 */
	public function getString( delimiter : String ) : String
	{
		if( !delimiter ) delimiter = ";";
		
		var list : Array = _extensions.getElements();
		var l : Number = list.length;
		var r : String = "";
		
		for( var i : Number = 0; i < l; i++ )
		{
			var ext : String = '*.' + list[i];
			r += ext;
			if( i+1 < l ) r+= delimiter;	
		}	
		return r;	
	}
	
	/**
	 * Returns an iterator throw filter collection.
	 * 
	 * <p>Here a simple ArrayIterator throw single content array
	 */
	public function getFilterIterator() : Iterator
	{
		return new ArrayIterator( new IndexedArray( this ) );
	}
	
	/**
	 * Indicates whether the given file is accepted by this filter.
	 * 
	 * @return {@code true} if file is ok, otherwise {@code false}
	 */
	public function accept( file : File ) : Boolean
	{
		if( file.isDirectory() || _extensions.length == 0 ) return true; 
      	if( _extensions.objectExists( '*' ) ) return true;
      	
		return _extensions.objectExists( file.getExtension() );
	}
	
	/**
	 * Returns a string representation of this filter.
	 */
	public function toString() : String
	{
		return _description;	
	}
	
}